/*
 * Javalin - https://javalin.io
 * Copyright 2017 David Åse
 * Licensed under Apache 2.0: https://github.com/tipsy/javalin/blob/master/LICENSE
 */

package io.javalin

import io.javalin.http.Header
import io.javalin.http.HttpStatus.NOT_MODIFIED
import io.javalin.http.HttpStatus.OK
import io.javalin.testing.TestUtil
import io.javalin.testing.httpCode
import kong.unirest.Unirest
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class TestEtags {

    private val etagsEnabledApp = Javalin.create { it.http.generateEtags = true }

    @Test
    fun `default app does not set etags for GET`() = TestUtil.test { app, http ->
        app.get("/") { it.result("Hello!") }
        assertThat(Unirest.get(http.origin + "/").asString().body).isEqualTo("Hello!")
        assertThat(Unirest.get(http.origin + "/").asString().httpCode()).isEqualTo(OK)
        assertThat(Unirest.get(http.origin + "/").asString().headers.getFirst(Header.ETAG)).isNullOrEmpty()
    }

    @Test
    fun `autogenerated etags are added to GET request`() = TestUtil.test(etagsEnabledApp) { app, http ->
        app.get("/automatic") { it.result("Hello!") }
        val response = Unirest.get(http.origin + "/automatic").asString()
        assertThat(response.httpCode()).isEqualTo(OK)
        assertThat(response.body).isEqualTo("Hello!")
        val etag = response.headers.getFirst(Header.ETAG)
        val response2 = Unirest.get(http.origin + "/automatic").header(Header.IF_NONE_MATCH, etag).asString()
        val etag2 = response2.headers.getFirst(Header.ETAG)
        assertThat(response2.httpCode()).isEqualTo(NOT_MODIFIED)
        assertThat(response2.body).isNullOrEmpty()
        assertThat(etag).isEqualTo(etag2)
    }

    @Test
    fun `etags are not autogenerated for input stream response`() = TestUtil.test(etagsEnabledApp) { app, http ->
        app.get("/inputStreamResult") { it.result(javaClass.getResourceAsStream("/public/file")!!) }
        val response = Unirest.get(http.origin + "/inputStreamResult").asString()
        assertThat(response.httpCode()).isEqualTo(OK)
        assertThat(response.body).isEqualTo("TESTFILE")
        val etag = response.headers.getFirst(Header.ETAG)
        assertThat(etag).isBlank()
    }

    @Test
    fun `autogenerated etags are not added to PUT request`() = TestUtil.test(etagsEnabledApp) { app, http ->
        app.put("/automatic") { it.result("Hello!") }
        val response = Unirest.put(http.origin + "/automatic").asString()
        assertThat(response.headers.getFirst(Header.ETAG)).isNullOrEmpty()
    }

    @Test
    fun `manual etags overwrite autogenerated etags`() = TestUtil.test(etagsEnabledApp) { app, http ->
        app.get("/manual") { it.result("Hello!").header(Header.ETAG, "1234") }
        val response = Unirest.get(http.origin + "/manual").asString()
        assertThat(response.httpCode()).isEqualTo(OK)
        assertThat(response.body).isEqualTo("Hello!")
        val etag = response.headers.getFirst(Header.ETAG)
        val response2 = Unirest.get(http.origin + "/manual").header(Header.IF_NONE_MATCH, etag).asString()
        assertThat(response2.httpCode()).isEqualTo(NOT_MODIFIED)
        assertThat(response2.body).isNullOrEmpty()
        assertThat(etag).isEqualTo("1234")
    }

    @Test
    fun `manual etags work for PUT request`() = TestUtil.test { app, http ->
        app.put("/manual") { it.result("Hello!").header(Header.ETAG, "1234") }
        val response = Unirest.put(http.origin + "/manual").asString()
        assertThat(response.headers.getFirst(Header.ETAG)).isEqualTo("1234")
    }

}
